// Biblioteca de numeros complexos para ser utilizada em compiladores C++
// Funcionamento verificado sob VC++, DJGPP e GCCs de UNIX
// Atencao : NAO UTILIZE #INCLUDE <COMPLEX.H> NO SEU SOURCE !!!
//		     COLOQUE O OPCOMPLX.H NO MESMO DIRETORIO DO SEU SOURCE E NELE
//           USE SOMENTE #INCLUDE "OPCOMPLX.H" !!!
// (c) 1999, Eduardo TUDA Lorenzetti Pellini <epellini@hipernet.com.br>
// Versao 1.1 - fevereiro de 1999


// include necessarios ...      math para funcoes matematicas genericas
//                              stdlib pq alguns compiladores precisam dela com a math
//                              stdio para funcoes de sprintf usadas na formatacao das saidas
#ifndef OPCOMPLX
#define OPCOMPLX
#define _COMPLEX_DEFINED

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define RAD 0           // RAD significa usar angulos em radianos
#define DEG 1           // DEG significa usar angulos em graus
#define IMREPRES 'j'    // que letra devo usar para representar o IMAGINARIO SQR(-1) !!
                        // tem gente que prefere o 'i'

class complex
{
public:
        double x,y;			// parte real e imaginaria
	
	// insercao dos numeros no objeto - na forma cartesiana ou polar
	void pol(double mag,double phase);		//insere na forma polar com angulos em radianos
    void pold(double mag, double phase);    //insere na forma polar com angulos em graus
	void rec(double a,double b);			//insere na forma cartesiana se nao quiser usar o .x e o .y
	
	double abs(void);	        // modulo
	double norm(void);	        // norma
	double phas(char angle);	// fase em 0 - radianos ou 1 - graus
    char *printr(void);         // retorna string com o complexo na forma retangular
    char *printp(char angle);   // mesma coisa da anterior mas na forma polar e 0 - rad ou 1 - graus

};

//funcoes aritmeticas
complex cconj (complex a);				//retorna o complexo conjugado
complex cmult (complex a, complex b);	//multiplica dois complexos
complex cdiv (complex a, complex b);	//divide dois complexos
complex cadd (complex a, complex b);	//adiciona dois complexos
complex csub (complex a, complex b);	//subtrai dois complexos
complex cpow (complex a, double pot);   //eleva `a pot potencia
complex cexp (complex a);				//faz exponencial de a  (e^a)

// overload de operadores para facilitar a vida do cidadao programador
complex operator + (complex a, complex b); //operador de adicao
complex operator - (complex a, complex b); //operador de subtracao
complex operator - (complex a);            //operador unario (-a)
complex operator * (complex a, complex b); //operador de multiplicacao
complex operator / (complex a, complex b); //operador de divisao
complex operator ^ (complex a, double b);  //operador de potenciacao com expoente real
complex operator ~ (complex a);            //operador de conjugado


//funcoes definidas na classe complex
void complex::pol(double mag, double phase)  // phase e' em rad !!!!
{
	x=mag*cos(phase);
	y=mag*sin(phase);
}

void complex::pold(double mag, double phase)  // phase e' em graus !!!!
{
        pol(mag,phase*atan(1)/45);
}

void complex::rec(double a, double b)
{
	x=a;	//chove no molhado
	y=b;
}

double complex::abs(void)
{
	return sqrt(x*x+y*y);	//santo pitagoras
}

double complex::norm(void)
{
	return (x*x+y*y);	//quadrado do modulo
}

double complex::phas(char angle)        //retorna fase em radianos se angle=0 ou graus se angle=1
{
        return (angle ? (45*atan2(y,x)/atan(1)) : atan2(y,x) );
}

char *complex::printr(void)             //retorna uma string bonita e menor possivel 8))
     {
      char *bigstring, *string;
      bigstring=new char[200];
      string=new char[sprintf(bigstring,"%g %+g%c",x,y,IMREPRES)+1];
      strcpy(string,bigstring);
      return string;
     }

char *complex::printp(char angle)       //indem anterior, mas na forma polar e com o angulo em RAD ou DEG
     {
      char *bigstring,*string;
      bigstring=new char[200];
      string=new char[sprintf(bigstring,"%g |_ %g%c",abs(),phas(angle),angle ? 248 : 0)+1];
      strcpy(string,bigstring);
      return string;
     }



// funcoes aritmeticas
complex cconj (complex a)	// que eu me lembre... so mudamos o sinal da parte imaginaria
{
	complex c;
	c.x=a.x;
	c.y=-a.y;
	return c;
}

complex cmult(complex a, complex b) // adivinha...multiplico dois complexos usando distributiva (blargh!)
{
	complex c;
	c.x=a.x*b.x-a.y*b.y;
	c.y=a.y*b.x+a.x*b.y;
	return c;
}

complex cdiv(complex a, complex b)	//tcham... que jeito de se dividir !! funciona, mas prefiro forma polar !
{
	complex c;
	c=cmult(a,cconj(b));
	c.x/=b.norm();
	c.y/=b.norm();
	return c;
}

complex cadd(complex a, complex b)      // maternal I
{
	complex c;
	c.x=a.x+b.x;
	c.y=a.y+b.y;
	return c;
}

complex csub(complex a, complex b)	//maternal II
{
	complex c;
	c.x=a.x-b.x;
	c.y=a.y-b.y;
	return c;
}

complex cpow(complex a, double pot) //malandragem... elevar `a potencia na forma polar e' bico
{
	complex c;
	c.pol(pow(a.abs(),pot),a.phas(RAD)*pot);
	return c;
}


complex cexp(complex a)
{
	complex c;
	c.x=exp(a.x)*cos(a.y);
	c.y=exp(a.x)*sin(a.y);
	return c;
}


// pra quem nao conhece ... esta e' a secao de overload de operadores  !!!
complex operator + (complex a, complex b)
        { return cadd(a,b); }

complex operator - (complex a, complex b)
        { return csub(a,b); }

complex operator - (complex a)
        { a.x=-a.x; a.y=-a.y; return a;}

complex operator * (complex a, complex b)
        { return cmult(a,b); }

complex operator / (complex a, complex b)
        { return cdiv(a,b); }

complex operator ^ (complex a, double b)
        { return cpow(a,b); }

complex operator ~ (complex a)
        { return cconj(a); }

#endif

// fim !!!
// Everything feito por Eduardo TUDA Lorenzetti Pellini
// (C) 1999, Direitos autorais liberados desde que nao se elimine a referencia acima 8-P




